/*
 * Copyright (C) 2007-2008  Hylke van der Schaaf
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, in version 3 of the License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */
package hextd.server;

import hextd.message.Message;
import hextd.message.MessageChannelJoin;
import hextd.message.MessageFactory;
import hextd.message.MessageFetch;
import hextd.message.MessagePlayerAuth;
import hextd.message.MessagePlayerInfo;
import hextd.message.MessagePlayerList.MPPlayerInfo;
import hextd.message.MessageReplayLogSP;
import hextd.network.LineListener;
import hextd.network.NetworkConnection;

public class Player implements LineListener {

	private Server server;
	private Channel channel;
	private boolean authenticated = false;
	private NetworkConnection connection;
	private int gameId = 0;
	private boolean ready = false;
	private PlayerInfo playerInfo;

	public Player(Server server, NetworkConnection connection) {
		this.connection = connection;
		this.server = server;
		this.connection.addLineListener(this);
	}

	public Channel getChannel() {
		return channel;
	}

	public void setChannel(Channel channel) {
		this.channel = channel;
		this.ready = false;
	}

	public void doAuth(String token) {
		System.out.println("Player::doAuth: doing auth for '" + token + "'");
		authenticated = server.authenticatePlayer(this, token);
		if (authenticated) {
			sendLine(MessagePlayerInfo.formatMessage(playerInfo));
		}
	}

	public boolean isAuthenticated() {
		return authenticated;
	}

	public void setAuthenticated(boolean authenticated) {
		this.authenticated = authenticated;
	}

	public NetworkConnection getConnection() {
		return connection;
	}

	public void sendLine(String line) {
		this.connection.sendLine(line);
	}

	@Override
	public void lineReceived(String line) {
		if (this.channel != null) {
			this.channel.receiveLine(this, line);
		} else {
			Message message = MessageFactory.GetMessage(line);
			switch (message.getType()) {
				case PlayerAuth:
					MessagePlayerAuth mpa = (MessagePlayerAuth) message;
					doAuth(mpa.getToken());
					break;
				case ChannelJoin:
					if (isAuthenticated()) {
						MessageChannelJoin mjc = (MessageChannelJoin) message;
						this.server.playerToChannel(this, mjc.getId());
					}
					return;
				case ReplayLogSP:
					MessageReplayLogSP mrl = (MessageReplayLogSP) message;
					mrl.setUserId(playerInfo.userId);
					server.addSpReplay(mrl);
					return;
				case Fetch:
					MessageFetch mf = (MessageFetch) message;
					server.fetchFromServer(mf, this);
					break;
				case PlayerInfo:
					MessagePlayerInfo mpi = (MessagePlayerInfo) message;
					if (playerInfo != null) {
						playerInfo.updateFrom(mpi.getPlayerInfo(), false);
					}
					break;
				case Unknown:
					System.out.println("Player::lineReceived: Unknown message: " + line);
					break;
				default:
					System.err.println("Player::lineReceived: Unknown message type: " + message.getType());
					break;
			}
		}
	}

	@Override
	public void inputStopped() {
		if (channel != null) {
			channel.playerLeft(this, "nowhere (Disconnected)");
			channel = null;
		}
		server.playerDisconnected(this);
	}

	public int getGameId() {
		return gameId;
	}

	public void setGameId(int gameId) {
		this.gameId = gameId;
	}

	public int getUserId() {
		return playerInfo.userId;
	}

	public String getUserName() {
		return playerInfo.userName;
	}

	public String getUserRights() {
		return playerInfo.userRights;
	}

	public int getRank() {
		return playerInfo.rank;
	}

	public int getGames() {
		return playerInfo.games;
	}

	public boolean isReady() {
		return ready;
	}

	public void setReady(boolean ready) {
		this.ready = ready;
	}

	public PlayerInfo getPlayerInfo() {
		return playerInfo;
	}

	public MPPlayerInfo getMPPlayerInfo() {
		MPPlayerInfo retval = new MPPlayerInfo();
		retval.gameId = gameId;
		retval.games = playerInfo.games;
		retval.name = playerInfo.userName;
		retval.rank = playerInfo.rank;
		retval.ready = ready;
		retval.userId = playerInfo.userId;
		return retval;
	}

	public void setPlayerInfo(PlayerInfo playerInfo) {
		this.playerInfo = playerInfo;
	}
}
